package com.irdstudio.basic.framework.core.util;

import java.security.MessageDigest;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import com.irdstudio.basic.framework.core.constant.PubConstant;


/**
 * 
 * ase加解密
 * 
 * @author Cytus_
 * @since 2018年5月17日 下午3:06:07
 * @version 1.0
 *
 */
public final class AESUtility {

	/**
	 * 密钥算法
	 */
	public static final String AES_KEY_ALGORITHM = "AES";

	/**
	 * 加解密算法/工作模式/填充方式
	 */
	public static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
	
	static java.util.Base64.Encoder encoder = java.util.Base64.getEncoder();

	/**
	 * AES加密: 使用原始字符串密钥，经MD5转成16字节密钥后，对字符串进行AES/ECB加密，PKCS5Padding。
	 * 
	 * @param src
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public final static String encryptMD5Key(String src, String key) throws Exception {
		return new String(encoder.encode(encryptMD5Key(src.getBytes(PubConstant.CHARSET_UTF_8), getMD5KeyBytes(key))));
	}
	
	/**
	 * AES加密: 使用原始字符串密钥，对字符串进行AES/ECB加密，PKCS5Padding。
	 * 
	 * @param src
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public final static String encrypt(String src, String key) throws Exception {
		return new String(encoder.encode(encrypt(src.getBytes(PubConstant.CHARSET_UTF_8), getMD5KeyBytes(key))));
	}

	/**
	 * 加密：使用原始密钥，经MD5转成16字节密钥后，对待加密字节进行AES/ECB加密，PKCS5Padding。
	 * 
	 * @param src：待加密字节
	 * @param key：原始密钥字节
	 * @return：加密后的字节
	 * @throws Exception
	 */
	public final static byte[] encryptMD5Key(byte[] src, byte[] key) throws Exception {
		if(key == null) {
			return null;
		}

		// 对原始密钥做MD5算hash值，得到16字节密钥
		MessageDigest alg = MessageDigest.getInstance(PubConstant.ALGORITHM_MD5);
		alg.update(key);
		byte[] key16 = alg.digest();

		SecretKeySpec skeySpec = new SecretKeySpec(key16, AES_KEY_ALGORITHM);
		Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);// "算法/模式/补码方式"
		cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
		byte[] encrypted = cipher.doFinal(src);

		return encrypted;
	}

	/**
	 * 加密：使用原始密钥，经MD5转成16字节密钥后，对待加密字节进行AES/ECB加密，PKCS5Padding。
	 * 
	 * @param src：待加密字节
	 * @param key：原始密钥字节
	 * @return：加密后的字节
	 * @throws Exception
	 */
	public final static byte[] encrypt(byte[] src, byte[] key16) throws Exception {
		SecretKeySpec skeySpec = new SecretKeySpec(key16, AES_KEY_ALGORITHM);
		Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);// "算法/模式/补码方式"
		cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
		return cipher.doFinal(src);
	}

	/**
	 * AES解密：使用原始字符串密钥，经MD5转成16字节密钥后，对加密后的base64字符串解密
	 * 
	 * @param base64src：base64编码的待解密字符串
	 * @param key
	 *            ：原始密钥
	 * @return：解密后的字符串
	 * @throws Exception
	 */
	public final static String decryptMD5Key(String str, String key) throws Exception {
		return new String(decryptMD5Key(Base64.decode(str), getMD5KeyBytes(key)), PubConstant.CHARSET_UTF_8);
	}

	/**
	 * AES解密：使用原始字符串密钥，经MD5转成16字节密钥后，对加密后的base64字符串解密
	 * 
	 * @param base64src：base64编码的待解密字符串
	 * @param key：原始密钥
	 * @return：解密后的字节
	 * @throws Exception
	 */
	public final static byte[] decryptMD5Key(byte[] src, byte[] key) throws Exception{
		if(key == null) {
			return null;
		}

		// 对原始密钥做MD5算hash值，得到16字节密钥
		MessageDigest alg = MessageDigest.getInstance(PubConstant.ALGORITHM_MD5);
		alg.update(key);
		byte[] key16 = alg.digest();

		SecretKeySpec skeySpec = new SecretKeySpec(key16, AES_KEY_ALGORITHM);
		Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
		cipher.init(Cipher.DECRYPT_MODE, skeySpec);
		return cipher.doFinal(src);

	}

	/**
	 * 计算16位长的密码byte值,对原始密钥做MD5算hash值
	 * 
	 * @param strKey
	 *            ：原始密钥
	 * @return：16字节密钥
	 * @throws Exception
	 */
	public final static byte[] getMD5KeyBytes(String strKey) throws Exception {
		if(null == strKey || strKey.length() < 1)
			throw new Exception("key is null or empty!");

		MessageDigest alg = MessageDigest.getInstance(PubConstant.ALGORITHM_MD5);
		alg.update(strKey.getBytes());
		return alg.digest();
	}

	/**
	 * 获得128位安全KEY
	 * @return
	 * @throws Exception
	 */
	public final static String getSecretKey() throws Exception {
		return getSecretKey(128);
	}
	
	/**
	 * 获得安全KEY
	 * @return
	 * @throws Exception
	 */
	public final static String getSecretKey(int length) throws Exception {
		KeyGenerator kg = KeyGenerator.getInstance(AES_KEY_ALGORITHM);
		kg.init(256);
		SecretKey sk = kg.generateKey();
		return new String(encoder.encode(sk.getEncoded()));
	}
	
	public static void main(String[] args) throws Exception {
        String s = encryptMD5Key("lp_piccs", "y3PsTEpHRnI9EZe0zBNeaIzi1225MEhGIJcaPzSBsKI=");
        System.out.println(s);
    }
}
